Skip to content

fix: resolve dark mode flicker issue#7533

Merged
saurabhraghuvanshii merged 10 commits intolayer5io:masterfrom
AnkitRewar11:fix/dark-mode-flicker-clean
Apr 10, 2026
Merged

fix: resolve dark mode flicker issue#7533
saurabhraghuvanshii merged 10 commits intolayer5io:masterfrom
AnkitRewar11:fix/dark-mode-flicker-clean

Conversation

@AnkitRewar11
Copy link
Copy Markdown
Contributor

@AnkitRewar11 AnkitRewar11 commented Mar 21, 2026

Description
This PR fixes #7443

This PR resolves the dark mode flicker issue. On page load, the theme
was not being applied before render which caused a visible flicker.
Updated ThemeManager.js, StyledThemeProvider.js, and onRenderBody.js
to properly handle theme initialization and prevent flash of unstyled
content (FOUC).

Notes for Reviewers

  • Updated ThemeManager.js to handle dark mode state properly
  • Updated StyledThemeProvider.js for consistent theme application
  • Updated onRenderBody.js to inject correct theme class before render
  • No new dependencies added
  • Only 3 files changed

Signed commits

  • Yes, I signed my commits.

Signed-off-by: ankitrewar11 <ankitrewar11@gmail.com>
@AnkitRewar11 AnkitRewar11 force-pushed the fix/dark-mode-flicker-clean branch from 68be4fd to a5c4a7d Compare March 21, 2026 13:49
@l5io
Copy link
Copy Markdown
Member

l5io commented Mar 21, 2026

🚀 Preview for commit a5c4a7d at: https://69bea5593286e0c4d4ee82dc--layer5.netlify.app

Copy link
Copy Markdown
Contributor

@YASHMAHAKAL YASHMAHAKAL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is much better @AnkitRewar11, Good to merge !!

@AnkitRewar11
Copy link
Copy Markdown
Contributor Author

@YASHMAHAKAL Thank you so much for the review and support! 🙏
Really appreciate your guidance throughout this PR.
Looking forward to getting it merged! 😊

@l5io
Copy link
Copy Markdown
Member

l5io commented Mar 21, 2026

🚀 Preview for commit 8d09e77 at: https://69befa12ca8054dc493243ab--layer5.netlify.app

@Bhumikagarggg
Copy link
Copy Markdown
Contributor

@AnkitRewar11 Want to merge this PR? Add it as an agenda item to the meeting minutes, if you would 🙂! Thank you for your contribution! Let's discuss this during the website call tomorrow at 5:30 PM IST | 7 AM CST.

@@ -1,22 +1,16 @@
//uses isDark state to choose styled-component theme (in themeStyles.js)
//and use ThemeProvider to allow all styled components access to values via props.theme

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these comments inaccurate or unhelpful?

If they are inaccurate because of the changes that you've made, then update what they say.

If they are not helpful, then update what they say.

// Apply to DOM immediately
applyThemeToDOM(themeToApply);

// Persist to localStorage
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reinstate the comments.

Comment thread onRenderBody.js
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was the existing approach completely ripped out and replaced?

What is precisely wrong with the current approach? Fix that.

If the current approach is completely offbase - ok - explain that and why a complete rewrite is needed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AnkitRewar11 can you answer this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @saurabhraghuvanshii, just wanted to clearly explain why the master branch approach was failing and how this PR fixes it.

I’ve only made a few focused fixes to solve the dark mode flicker issue:

Wrong Injection Placement: The script was running too late (inside ), so the page first showed light mode. I moved it to so the correct theme loads before anything is displayed.

Missing data-theme: The code wasn’t setting the data-theme attribute on the HTML root, which is needed for dark mode styles. I’ve added that.

SSR / Hydration Mismatch: The server knew the theme, but the frontend didn’t, so it defaulted to light mode and caused flicker. I fixed this by passing the theme (window.__theme) so both stay in sync.

JSON Parsing Issue: The previous way of parsing theme data could break if there were quotes in the string. I made it safer to avoid crashes.

Now the changes are minimal, clean, and focused and the flicker issue is completely resolved. I hope all your questions have been answered. If there’s anything else you’d like to know, please let me know.

@leecalcote
Copy link
Copy Markdown
Member

@AnkitRewar11 without details as to where specifically we're failing in the current implementation, and without details as to how your completely new approach resolves the problem, we're flying blind - - and this doesn't work.

Refactor StyledThemeProvider to ensure consistent theme rendering for SSR.

Signed-off-by: Ankit Rewar <171806101+AnkitRewar11@users.noreply.github.com>
Signed-off-by: Ankit Rewar <171806101+AnkitRewar11@users.noreply.github.com>
Refactor theme handling logic in MagicScriptTag component. Update the way themes are injected into the document and change the function signature for onRenderBody.

Signed-off-by: Ankit Rewar <171806101+AnkitRewar11@users.noreply.github.com>
Updated comments for clarity and added a fallback for SSR-injected CSS variables during hydration.

Signed-off-by: Ankit Rewar <171806101+AnkitRewar11@users.noreply.github.com>
@l5io
Copy link
Copy Markdown
Member

l5io commented Mar 23, 2026

🚀 Preview for commit 9ad62cb at: https://69c0e4f81e80d04a59c24468--layer5.netlify.app

@l5io
Copy link
Copy Markdown
Member

l5io commented Mar 23, 2026

🚀 Preview for commit 9736016 at: https://69c0f0bce6282fe4fa13bfa3--layer5.netlify.app

@AnkitRewar11 AnkitRewar11 force-pushed the fix/dark-mode-flicker-clean branch 2 times, most recently from 2048e58 to 42eab57 Compare March 23, 2026 08:22
@l5io
Copy link
Copy Markdown
Member

l5io commented Mar 23, 2026

🚀 Preview for commit 42eab57 at: https://69c0fbc40e47164cd82d99e2--layer5.netlify.app

@AnkitRewar11 AnkitRewar11 force-pushed the fix/dark-mode-flicker-clean branch from 42eab57 to f00fabd Compare March 23, 2026 09:48
@l5io
Copy link
Copy Markdown
Member

l5io commented Mar 23, 2026

🚀 Preview for commit f00fabd at: https://69c10fd10e471689402d9987--layer5.netlify.app

… fixes with comments

Signed-off-by: Ankit Rewar <AnkitRewar11@users.noreply.github.com>
@AnkitRewar11 AnkitRewar11 force-pushed the fix/dark-mode-flicker-clean branch from f00fabd to f60787a Compare March 23, 2026 10:22
@YASHMAHAKAL
Copy link
Copy Markdown
Contributor

@AnkitRewar11 even this time you've responded to review with 5-6 new commits. and the description you post after your commits, it was even relevant to your first commit, and about diff's looking easy, they were much easy before : )

correct me if i'm wrong, Thanks for your efforts 👍

@AnkitRewar11
Copy link
Copy Markdown
Contributor Author

@AnkitRewar11 even this time you've responded to review with 5-6 new commits. and the description you post after your commits, it was even relevant to your first commit, and about diff's looking easy, they were much easy before : )

correct me if i'm wrong, Thanks for your efforts 👍

You were right my previous approach was also correct. But yesterday Lee suggested a few changes, like adding the comments again, and I’ve done that now.

As for the current approach, there isn’t much difference between the two. I just made minimal changes to the old code so that it’s easier to understand.

And regarding the new commits, I accidentally made the changes directly here instead of locally, so that’s why so many commits were created. Sorry about that.

@AnkitRewar11 AnkitRewar11 requested a review from leecalcote March 24, 2026 05:37
const initialColorValue = (root.style.getPropertyValue("--initial-color-mode") || "").trim();
const actualTheme = window.__theme || initialColorValue || ThemeSetting.LIGHT;

// Get stored theme from localStorage
Copy link
Copy Markdown
Member

@rishiraj38 rishiraj38 Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don’t remove the comments.

Copy link
Copy Markdown
Contributor Author

@AnkitRewar11 AnkitRewar11 Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @rishiraj38, I hope everything got added properly. I’ve added that one comment as you suggested.

@AnkitRewar11 AnkitRewar11 force-pushed the fix/dark-mode-flicker-clean branch from 72c475b to 3a170b6 Compare March 31, 2026 12:18
@AnkitRewar11 AnkitRewar11 requested a review from rishiraj38 March 31, 2026 12:19
@l5io
Copy link
Copy Markdown
Member

l5io commented Mar 31, 2026

🚀 Preview for commit 3a170b6 at: https://69cbbf473ddc3f5da4372c0f--layer5.netlify.app

@rishiraj38
Copy link
Copy Markdown
Member

@saurabhraghuvanshii, could you please take a look at this PR?

@l5io
Copy link
Copy Markdown
Member

l5io commented Mar 31, 2026

🚀 Preview for commit 00e3368 at: https://69cc166e700405aa29e3d071--layer5.netlify.app

@l5io
Copy link
Copy Markdown
Member

l5io commented Apr 2, 2026

🚀 Preview for commit 2dc387a at: https://69ce48ebf7b0d22bdba1b3a4--layer5.netlify.app

Comment thread onRenderBody.js Outdated
Comment thread src/theme/app/ThemeManager.js Outdated
@AnkitRewar11 AnkitRewar11 force-pushed the fix/dark-mode-flicker-clean branch from 2dc387a to bc5a6da Compare April 3, 2026 09:27
@l5io
Copy link
Copy Markdown
Member

l5io commented Apr 3, 2026

🚀 Preview for commit bc5a6da at: https://69cf8b5fc52dd1b6e3c3ee10--layer5.netlify.app

@AnkitRewar11 AnkitRewar11 requested a review from rishiraj38 April 4, 2026 19:36
@rishiraj38 rishiraj38 requested a review from YASHMAHAKAL April 4, 2026 19:38
Comment thread src/theme/app/StyledThemeProvider.js
Comment thread onRenderBody.js
Copy link
Copy Markdown
Contributor

@YASHMAHAKAL YASHMAHAKAL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good work btw, thanks @AnkitRewar11

@YASHMAHAKAL
Copy link
Copy Markdown
Contributor

@AnkitRewar11 I'll encourage you to add this PR as an agenda item to the meeting minutes, if you would 🙂! Thank you for your contribution! Let's discuss this during the website call tomorrow at 5:30 PM IST | 7 AM CST.

Signed-off-by: Ankit Rewar <AnkitRewar11@users.noreply.github.com>
@AnkitRewar11 AnkitRewar11 force-pushed the fix/dark-mode-flicker-clean branch from bc5a6da to 4491cc1 Compare April 5, 2026 20:48
@arjunmehta-git
Copy link
Copy Markdown

This has come a long way, @AnkitRewar11, and your detailed explanation of the four root causes (script placement in setPreBodyComponents vs setHeadComponents, missing data-theme attribute, window.__theme SSR handoff, and the JSON.parse crash risk) is exactly the kind of analysis that helps reviewers understand and trust the fix.

Since this has approvals from both @YASHMAHAKAL and @rishiraj38 on the current commit, and the core FOUC mechanism is well-explained, I'd like to see one final thing before this merges:

  • Manual FOUC verification — Please test by hard-refreshing the Netlify preview in both light and dark mode (with the mode stored in localStorage) and confirm there is no visible flash. A short screen recording or a "tested, no flicker observed" comment from a reviewer who verified the Netlify preview would close this out.

One process note for future PRs: responding to review feedback by pushing many small fixup commits makes the diff harder to follow. Consider squashing fixup commits locally (git rebase -i) before pushing so the history stays readable. It also makes it easier for reviewers to see the net effect of your changes.

Good work seeing this through.

@AnkitRewar11
Copy link
Copy Markdown
Contributor Author

This has come a long way, @AnkitRewar11, and your detailed explanation of the four root causes (script placement in setPreBodyComponents vs setHeadComponents, missing data-theme attribute, window.__theme SSR handoff, and the JSON.parse crash risk) is exactly the kind of analysis that helps reviewers understand and trust the fix.

Since this has approvals from both @YASHMAHAKAL and @rishiraj38 on the current commit, and the core FOUC mechanism is well-explained, I'd like to see one final thing before this merges:

  • Manual FOUC verification — Please test by hard-refreshing the Netlify preview in both light and dark mode (with the mode stored in localStorage) and confirm there is no visible flash. A short screen recording or a "tested, no flicker observed" comment from a reviewer who verified the Netlify preview would close this out.

One process note for future PRs: responding to review feedback by pushing many small fixup commits makes the diff harder to follow. Consider squashing fixup commits locally (git rebase -i) before pushing so the history stays readable. It also makes it easier for reviewers to see the net effect of your changes.

Good work seeing this through.

Thanks for the detailed review and guidance, @arjunmehta-git.

Currently, we are not using Netlify. I am waiting for the GitHub Actions Pages setup to be completed so I can provide final verification proof (screen recording or confirmation).

The FOUC-related changes have been tested locally, and no visible flash was observed. I will share final verification once the setup is ready.

Please let me know if anything else should be validated before merge. Appreciate the feedback and support. 🫡🙏

@saurabhraghuvanshii saurabhraghuvanshii merged commit 1f6034d into layer5io:master Apr 10, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dark mode flicker — white background appears briefly before theme loads

8 participants